﻿using System;
using System.Collections.Generic;
using ServerFramework.Tools;
using System.Configuration;
using System.Threading.Tasks;
using System.Threading;
using ServerFramework.Db;
using System.Collections.Concurrent;


namespace ServerFramework.ORM
{
    /// <summary>
    /// 数据库提交对象
    /// </summary>
    public class DbSqlInfo
    {
        public string DbName { get; set; }
        public string Sql { get; set; }
    }
    /// <summary>
    /// 用来负责管理entity 修改提交
    /// </summary>
    public class DbEntityManager
    {
        private static DbEntityManager _instance;
        public static DbEntityManager Instance { get { if (_instance == null) { _instance = new DbEntityManager(); } return _instance; } }
        /// <summary>
        /// 提交数据间隔时间
        /// </summary>
        private int COMMIT_DB_DETAL_SECONDS = 300;
     
        /// <summary>
        /// 删除队列
        /// </summary>
        protected ConcurrentQueue<DataEntityBase> _removeQueue = new ConcurrentQueue<DataEntityBase>();

        private Dictionary<string, ConnectionStringSettings> _dbSettings = new Dictionary<string, ConnectionStringSettings>();

        private System.Threading.Thread _thread = null;    //用来数据修改线程
        private bool _run = false;
        private DateTime _lastTime = DateTime.Now;

        private ShareDataCache _shareCache = null;      //共享数据缓存
        private PersonDataCache _personCache = null;    //私有数据缓存

        public ShareDataCache ShareCache { get { return _shareCache; } }
        public PersonDataCache PersonCache { get { return _personCache; } }

        
        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="commitSeconds">间隔提交时间 单位秒</param>
        public void Init(int commitIntervalSeconds = 300)
        {
            ORMHelper.CheckAssemblyAllTables();
            COMMIT_DB_DETAL_SECONDS = commitIntervalSeconds;
            ///将所有的数据库配置缓存起来
            foreach (ConnectionStringSettings connection in ConfigurationManager.ConnectionStrings)
            {
                _dbSettings.Add(connection.Name, connection);
            }
            _shareCache = new ShareDataCache();
            _personCache = new PersonDataCache();
            StartUpdateDb();
        }


        /// <summary>
        /// 开始起动提交线程
        /// </summary>
        private void StartUpdateDb()
        {
            _thread = new System.Threading.Thread(Worker);
            _run = true;
            _thread.Start();
            _lastTime = DateTime.Now;
        }

        /// <summary>
        /// 项数据库提交工作线程
        /// </summary>
        private void Worker()
        {
            Log.WriteLog(ELogLevel.LOG_INFO, "db commit start success");
            while (_run)
            {
                if ((DateTime.Now - _lastTime).TotalSeconds > COMMIT_DB_DETAL_SECONDS)
               {
                   UpdateEntitys();
                   _lastTime = DateTime.Now;
               }
               Thread.Sleep(20);
            }

            Log.WriteLog(ELogLevel.LOG_INFO, "正在提交剩余数据...");
            UpdateEntitys();
            Log.WriteLog(ELogLevel.LOG_INFO, "提交剩余数据完成...");
            Log.WriteLog(ELogLevel.LOG_INFO,"按任意键退出");
            Console.ReadKey();
        }

        /// <summary>
        ///更新entity
        /// </summary>
        private void UpdateEntitys()
        {

           // DateTime start = DateTime.Now;

            Dictionary<string, List<string>> deleteSqls = new Dictionary<string, List<string>>();
            Dictionary<string, List<string>> addSqls = new Dictionary<string, List<string>>();
            Dictionary<string, List<string>> updateSqls = new Dictionary<string, List<string>>();
            while(_removeQueue.Count != 0)
            {
                DataEntityBase entity = null; ;
                if(_removeQueue.TryDequeue(out entity))
                {
                    string dbName = entity.GetDbName();
                    if (deleteSqls.ContainsKey(dbName))
                    {
                        deleteSqls[dbName].Add(ORMHelper.GetEntityDeleteSql(entity));
                    }
                    else
                    {
                        deleteSqls.Add(dbName, new List<string>() { ORMHelper.GetEntityDeleteSql(entity) });
                    }
                }
            }
            var entiyList = _shareCache.GetAllEntitys();
            entiyList.AddRange(_personCache.GetAllEntitys());
            foreach (var ent in entiyList)
            {
                if(ent.GetState() == EEntityState.Add)
                {
                    string dbName = ent.GetDbName();
                    if (addSqls.ContainsKey(dbName))
                    {
                        addSqls[dbName].Add(ORMHelper.GetEntityInsertSql(ent));
                    }
                    else
                    {
                        addSqls.Add(dbName, new List<string>() { ORMHelper.GetEntityInsertSql(ent) });
                    }
                }
                else if (ent.GetState() == EEntityState.Update)
                {
                    string dbName = ent.GetDbName();
                    if (updateSqls.ContainsKey(dbName))
                    {
                        updateSqls[dbName].Add(ORMHelper.GetEntityUpdateSql(ent));
                    }
                    else
                    {
                        updateSqls.Add(dbName, new List<string>() { ORMHelper.GetEntityUpdateSql(ent) });
                    }
                }
                ent.SetState(EEntityState.None);
            }

            //执行事务

            ///先删除
            foreach (var d in deleteSqls)
            {
                DbProvider dbp = GetProvider(d.Key);
                dbp.ExecuteSqlTran(d.Value);
                dbp.Close();
            }

            //在插入
            foreach (var a in addSqls)
            {
                DbProvider dbp = GetProvider(a.Key);
                dbp.ExecuteSqlTran(a.Value);
                dbp.Close();
            }
            //更新数据
            foreach (var u in updateSqls)
            {
                DbProvider dbp = GetProvider(u.Key);
                dbp.ExecuteSqlTran(u.Value);
                dbp.Close();
            }
        //    Log.WriteLog(ELogLevel.LOG_DEBUG, "take " + (DateTime.Now - start).TotalMilliseconds.ToString());
        }
        /// <summary>
        /// 删除entity
        /// </summary>
        /// <param name="entity"></param>
        public void AddRemoveEntity(DataEntityBase entity)
        {
            _removeQueue.Enqueue(entity);
        }

        /// <summary>
        /// 通过名字获取连接者
        /// </summary>
        /// <param name="dbName"></param>
        /// <returns></returns>
        private DbProvider GetProvider(string dbName)
        {
            DbProvider db = null;
            if (_dbSettings.ContainsKey(dbName))
            {
                db = DbHelper.CreateDbProvider(_dbSettings[dbName]);
                db.Open();
            }
            return db;
        }



        public void Release()
        {
            _run = false;
        }
    }
}
